/*
  This file is part of bnc.

  bnc is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  bnc is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with bnc.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "./stack.h"

void stackConstructor (stack* aStack)
{
  /*
    At the beginning there was nothing but empty stack
  */
  aStack->pStack=0;
  aStack->pSize=0;
}

node* stackPop (stack* aStack)
{
  /*
    Give me the one from the top. Do not leave any evidence of its existance.

    Decrease the stack size.
    Return pointer to the last node on the stack.
  */
  node* lRet;

  if (aStack->pSize==0) return 0;
  aStack->pSize--;
  lRet=aStack->pStack[aStack->pSize];
  aStack->pStack=(node**)realloc(aStack->pStack, aStack->pSize*sizeof(node*));
  return lRet;
}

void stackPush (stack* aStack, node* aHayFork)
{
  /*
    Place one onto the stack. Throw a hayfork into the stack.
  */
  aStack->pSize++;
  aStack->pStack=(node**)realloc(aStack->pStack, aStack->pSize*sizeof(node*));
  aStack->pStack[aStack->pSize-1]=aHayFork;
}

unsigned int stackSize (stack* aStack)
{
  /*
    Tell me how big the stack is.
  */
  return aStack->pSize;
}

node* stackTop (stack* aStack, unsigned int aOffset)
{
  /*
    Tell me what is on the offset position from the top but leave it untouched.
  */
  if (aStack->pSize==0) return 0;
  return aStack->pStack[aStack->pSize-aOffset-1];
}

void stackSort (stack* aStack, unsigned int aDepth)
{
  /*
    Sort the elements from the top decreasingly to the given depth.

    Bubble sort is used.
  */
  node* lTmp;
  unsigned int i;

  for (i=aStack->pSize-aDepth; i<aStack->pSize-1 && aStack->pSize>1; i++)
    if (nodeGetWeight(aStack->pStack[i])>nodeGetWeight(aStack->pStack[i+1]))
    {
      lTmp=aStack->pStack[i];
      aStack->pStack[i]=aStack->pStack[i+1];
      aStack->pStack[i+1]=lTmp;

      i=aStack->pSize-aDepth-1;
    }
}

void stackDestructor (stack* aStack)
{
  /*
    Get rid of the entire stack.
  */
  if (aStack->pStack)
  {
    unsigned int i;

    for (i=0; i<aStack->pSize; i++) free(aStack->pStack[i]);
    free(aStack->pStack);
  }
}
